layui.define(['form'], function (exports) {

    var $ = layui.$
        , form = layui.form
        , MOD_NAME = 'autoForm'
        , autoForm = {
        config: {}
        , index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0
        , set: function (options) {
            var that = this;
            that.config = $.extend({}, that.config, options);
            return that;
        }
        , on: function (events, callback) {
            return layui.onevent.call(this, MOD_NAME, events, callback);
        }
        // 提供外部显隐表单底部按钮的方法
        , showFormFooter: function (show, id) {
            let formAddEdit
            if (!id) {
                // 隐藏所有表单底部按钮
                formAddEdit = $(".layui-form-item:last")
            } else {
                formAddEdit = $(id);
            }
            var formFooter = formAddEdit.find(".layui-form-item:last");
            if (show) {
                formFooter.show();
            } else {
                formFooter.hide();
            }
        }
    }
        , thisModule = function () {
        var that = this
            , options = that.config
            , id = that.elem || that.index;

        if (!id) {
            return console.log('AutoForm 没有找到' + options.index + '实例');
        }

        thisModule.that[id] = that; //记录当前实例对象
        // thisModule.config[id] = options; //记录当前实例配置项
        return {
            config: options
            , reload: function (options) {
                that.reload.call(that, options);
            }
        }
    }
        , AutoForm = function (options) {
        this.config = options;
        this.elem = options.elem;
        this.renderArray = options.renderArray || [];
        this.index = ++autoForm.index;
        this.render();
    };

    AutoForm.prototype.render = function () {
        let formHtml = '';

        this.renderArray.forEach(item => {
            // 根据type和其他attr拼接表单HTML
            formHtml += this.createFormItem(item);
        })

        // let formElem = `<form>${formHtml}</form>`;
        let formElem = formHtml;

        // 表单底部按钮
        formElem += `<div class="layui-form-item impbtns">
                        <div class="layui-input-block">
                            <button type="button" class="w-button w-button--default is-default" onclick="layer.closeAll();"><span>${this.config.btns && this.config.btns[0] || '取消'}</span></button>
                            <button id="autoFormSubmit" type="submit" class="w-button w-button--primary is-primary" lay-submit="" lay-filter="autoFormSubmit"><span>${this.config.btns && this.config.btns[1] || '确定'}</span></button>
                        </div>
                     </div>`;

        // 渲染到container中
        $(this.elem).html(formElem);

        //绑定事件
        this.events();
    };

    AutoForm.prototype.createFormItem = function (item) {
        // 根据item的type和其他attr拼接表单HTML
        // 如果item.required为true，那么就在label中加上必填的标识
        let label = `<label class="layui-form-label ${item.required ? 'required' : ''}">${item.label} ${item.required ? '<i>*</i>' : ''}</label>`;
        let inputHtml = '';
        // 与label和inputHtml同级的额外的HTML
        let extraHtml = item.extraHtml || '';
        // 公用属性
        let commonAttrs = `name='${item.field}'
                    id='${item.field}'
                    ${item.required ? `lay-verify='required' lay-reqtext='请填写${item.label}'` : ''}
                    lay-filter="${item.field}Fil"`
        if (item.type === 'select') {
            // 渲染 select
            let optionsHtml = '';
            item.options && item.options.forEach(option => {
                optionsHtml += `<option value="${option.value}">${option.label}</option>`;
            });
            inputHtml = `<div class="layui-input-block">
                            <select
                                lay-search
                                ${commonAttrs}
                                ${item.inputAttrs || ''}>
                                ${optionsHtml}
                                </select>
                         </div>`
        }
        if (item.type === 'input') {
            // 渲染 input
            inputHtml = `
                <div class="layui-input-block">
                    <input
                    type="text"
                    placeholder="请输入${item.label}"
                    class="layui-input"
                    ${commonAttrs}
                    ${item.inputAttrs || ''}>
                </div>`
        }

        if (item.type === 'textarea') {
            // 渲染 textarea
            inputHtml = `
                <div class="layui-input-block">
                    <textarea
                    placeholder="请输入${item.label}"
                    class="layui-textarea"
                    ${commonAttrs}
                    ${item.inputAttrs || ''}></textarea>
                </div>`
        }

        if (item.type === 'tips') {
            return `<div class="layui-form-item imptip" ${item.formItemAttrs || ''}>
                        <div class="layui-input-block"><span id="${item.field}">${item.text}</span></div>
                    </div>`;
        }

        // 自定义表单项
        if (item.type === 'custom') {
            return item.html;
        }

        return `
         <div class="layui-form-item" ${item.formItemAttrs || ''}>
          ${label}
          ${inputHtml}
          ${extraHtml}
         </div>`;
    };

    // 绑定事件
    AutoForm.prototype.events = function () {
        let that = this;
        // 绑定事件
        this.renderArray.forEach(item => {
            if (item.change && typeof item.change === 'function') {
                form.on('select(' + item.field + 'Fil)', function (data) {
                    item.change(data);
                });
            }
        })
        // 表单提交
        if (this.config.submit && typeof this.config.submit === 'function') {
            form.on('submit(autoFormSubmit)', function (data) {
                that.config.submit(data);
                return false;
            });
        }
    }

    // 重载表单
    AutoForm.prototype.reload = function (options) {
        // 重新渲染表单
        this.renderArray = options.renderArray;
        this.render();
    }

    // 禁用表单内所有表单项
    AutoForm.prototype.disable = function (isDisabled) {
        // 直接操作dom
        if (isDisabled) {
            $(this.elem).find('input,select,textarea').attr('disabled', 'disabled');
        } else {
            $(this.elem).find('input,select,textarea').removeAttr('disabled');
        }
    }

    // 禁用表单内指定表单项
    AutoForm.prototype.disableItem = function (isDisabled, field) {
        // 直接操作dom, field为数组
        if (isDisabled) {
            field.forEach(item => {
                $(this.elem).find('#' + item).attr('disabled', 'disabled');
            })
        } else {
            field.forEach(item => {
                $(this.elem).find('#' + item).removeAttr('disabled');
            })
        }
    }

    // 显隐表单内指定表单项
    AutoForm.prototype.showItem = function (isShow, field) {
        // 直接操作dom, field为数组
        if (isShow) {
            field.forEach(item => {
                // 显示时，根据this.renderArray中的配置，如果是必填项，那么就要加上必填项的标识
                this.renderArray.forEach(renderItem => {
                    if (renderItem.field === item && renderItem.required) {
                        $(this.elem).find('#' + item).attr('lay-verify', 'required').attr('lay-reqtext', '请填写' + renderItem.label);
                    }
                })
                $(this.elem).find('#' + item).parent().parent().show()
            })
        } else {
            field.forEach(item => {
                // 隐藏时，如果是必填项，那么就要去掉必填项的标识，同时清空表单项的值
                $(this.elem).find('#' + item).parent().parent().hide()
                // 如果是select，不清空值，因为select的值手动清空存在校验失效的问题
                if ($(this.elem).find('#' + item)[0].tagName === 'SELECT') {
                    return
                }
                $(this.elem).find('#' + item).removeAttr('lay-verify').removeAttr('lay-reqtext').val('');
            })
        }
    }

    // 获取表单中，存在name属性并且name属性的值不为空，并且display不为none的表单项的值
    AutoForm.prototype.getValues = function () {
        let values = {};
        $(this.elem).find('[name]').each(function () {
            if ($(this).parent().parent().css('display') !== 'none') {
                $(this).attr('name') && (values[$(this).attr('name')] = $(this).val())
            }
        })
        return values;
    }

    // 记录所有实例
    thisModule.that = {}; //记录所有实例对象

    // 获取当前实例配对象
    thisModule.getThis = function (id) {
        var that = thisModule.that[id];
        if (!that) console.log(id ? (MOD_NAME + ' instance with ID \'' + id + '\' not found') : 'ID argument required');
        return that
    };

    autoForm.getModel = function (id) {
        return thisModule
    }

    // 禁用表单
    autoForm.disable = function (isDisabled, id) {
        if (id) {
            // 如果id为数组或者字符串，那么就是禁用指定的表单项；如果id为对象，key为表单id，value为禁用项的数组
            if (typeof id === 'string' || Array.isArray(id)) {
                for (let i in thisModule.that) {
                    thisModule.that[i].disableItem(isDisabled, [id]);
                }
            }
            if (Array.isArray(id)) {
                for (let i in thisModule.that) {
                    thisModule.that[i].disableItem(isDisabled, id);
                }
                return;
            }
            if (typeof id === 'object') {
                for (let i in id) {
                    thisModule.that[i].disableItem(isDisabled, id[i]);
                }
            }
            form.render();
        } else {
            for (let i in thisModule.that) {
                thisModule.that[i].disable(isDisabled);
            }
        }
    }

    // 显隐表单项
    autoForm.show = function (id) {
        // 一般情况下，id为数组或者字符串，如果id为对象，key为表单id，value为禁用项的数组
        if (typeof id === 'string' || Array.isArray(id)) {
            for (let i in thisModule.that) {
                thisModule.that[i].showItem(true, [id]);
            }
        }
        if (Array.isArray(id)) {
            for (let i in thisModule.that) {
                thisModule.that[i].showItem(true, id);
            }
            return;
        }
        if (typeof id === 'object') {
            for (let i in id) {
                thisModule.that[i].showItem(true, id[i]);
            }
        }
    }

    // 显隐表单项
    autoForm.hide = function (id) {
        // 一般情况下，id为数组或者字符串，如果id为对象，key为表单id，value为禁用项的数组
        if (typeof id === 'string' || Array.isArray(id)) {
            for (let i in thisModule.that) {
                thisModule.that[i].showItem(false, [id]);
            }
        }
        if (Array.isArray(id)) {
            for (let i in thisModule.that) {
                thisModule.that[i].showItem(false, id);
            }
            return;
        }
        if (typeof id === 'object') {
            for (let i in id) {
                thisModule.that[i].showItem(false, id[i]);
            }
        }
    }

    // 获取表单中display不为none的表单项的值
    autoForm.val = function (id) {
        // 判断id是否以#开头，如果是，那么就是获取指定表单项的值，否则添加#
        if (id.indexOf('#') !== 0) {
            id = '#' + id;
        }
        var that = thisModule.that[id];
        if (!that) console.log(id ? (MOD_NAME + ' instance with ID \'' + id + '\' not found') : 'ID argument required');
        return that.getValues();
    }

    //重载实例
    autoForm.reload = function (id, options) {
        var that = thisModule.that[id];
        that.reload(options);

        return thisModule.call(that);
    };

    // 核心入口
    autoForm.render = function (options) {
        var inst = new AutoForm(options);
        return thisModule.call(inst);
    }

    // 暴露模块
    exports(MOD_NAME, autoForm);
});
